iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
佛心分享-IT 人自學之術

ASP.NET Core 30日成長路系列 第 24

Day24:如何用Html Helpers建立CRUD表單

  • 分享至 

  • xImage
  •  

如何用Html Helpers建立CRUD表單


今天我們要來學的就是相較於用Scaffolding來的更複雜一點的方法,也就是用Html Helpers建立CRUD表單~
雖然說是比較複雜啦,但就是先用EF Core中的Migrations建立資料庫,完成後分別建立CRUD的動作,再用動作去建立檢視而已,拆成單一部份去看還是容易一點的。
那下面就開始實作啦~GoGo!

用EF Core中的Migrations建立資料庫
1️⃣在Models資料夾中建立Employee與Register資料模型
路徑🔗Models/Employee.cs

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Mobile { get; set; }
    public string Email { get; set; }
    public string Department { get; set; }
    public string Title { get; set; }
}

路徑🔗Models/Register.cs

{
    public class Register
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Nickname { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public int Gender { get; set; }
        public int City { get; set; }
        public string Commutermode { get; set; }
        public string Comment { get; set; }
        public bool Terms { get; set; }
    }
}

2️⃣以【Nuget套件管理員】安裝下圖EF Core與SqlServer等相關套件
https://ithelp.ithome.com.tw/upload/images/20241015/20167550Qf2VfmryWo.png

3️⃣在Data資料夾建立CmsContext類別及種子資料
路徑🔗Data/CmsContext.cs


namespace Mvc7_HtmlHelpers.Data
{
    public class CmsContext : DbContext
    {
        public CmsContext(DbContextOptions<CmsContext> options)
            : base(options)
        {
        }

        public DbSet<Employee> Employees { get; set; }
        public DbSet<Register> Registers { get; set; }


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Employee>().HasData(
                new Employee { Id = 1, Name = "David", Mobile = "0933-152667", Email = "david@gmail.com", Department = "總經理室", Title = "CEO" },
                new Employee { Id = 2, Name = "Mary", Mobile = "0938-456889", Email = "mary@gmail.com", Department = "人事部", Title = "管理師" },
                new Employee { Id = 3, Name = "Joe", Mobile = "0925-331225", Email = "joe@gmail.com", Department = "財務部", Title = "經理" },
                new Employee { Id = 4, Name = "Mark", Mobile = "0935-863991", Email = "mark@gmail.com", Department = "業務部", Title = "業務員" },
                new Employee { Id = 5, Name = "Rose", Mobile = "0987-335668", Email = "rose@gmail.com", Department = "資訊部", Title = "工程師" }
            );

            modelBuilder.Entity<Register>().HasData(
                new Register { Id = 1, Name = "奚江華", Nickname = "聖殿祭司", Password = "myPassword*", Email = "dotnetcool@gmail.com", City = 4, Gender = 1, Commutermode = "1", Comment = "Nothing", Terms = true }
                );
        }
    }
}

說明📄
1.DbContext➡️負責執行時期的Entity物件管理,包括從資料庫讀取資料、追蹤異動及資料寫入資料庫。
2.DbSet➡️用來查詢和儲存Entity個體資料,LINQ查詢是以DbSet為對象,然後LINQ語法會被轉成SQL查詢語法。

4️⃣在appsettings.json新增「CmsContext」資料庫連線設定
路徑🔗appsettings.json

{
...
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "CmsContext": "Server=(localdb)\\mssqllocaldb;Database=CmsDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

5️⃣在DI Container中註冊CmsContext
路徑🔗Program.cs

//取得組態中資料庫連線設定
string connectionString = builder.Configuration.GetConnectionString("CmsContext");

//註冊UEF Core的CmsContext
builder.Services.AddDbContext<CmsContext>(options => options.UseSqlServer(connectionString));

說明📄
在DI Container中註冊CmsContext後,才能在Controller或其他程式中以DI注入服務。在options中設定了兩點:1.使用SQL Server Provider提供者。2.使用CmsContext資料庫連線。

6️⃣在【套件管理主控台】新增Migration
Add-Migration InitialDB

7️⃣執行「Update-Database」命令更新資料庫
Update-Database

顯示員工清單資料
1️⃣在Controllers資料夾新增Employees控制器,以DI注入CmsContext,建立Index()程式讀取員工資料。
路徑🔗Controllers/EmployeesController.cs

public class EmployeesController : Controller
{
    private readonly CmsContext _context;
    //以DI注入CmsContext
    public EmployeesController(CmsContext context)
    {
        _context = context;
    }

    // GET: Employees
     public async Task<IActionResult> Index()
 {
     //從資料庫讀取資料,指派給employees物件
     var employees = await _context.Employees.ToListAsync();

     return View(employees);
 }

2️⃣在Index()方法按滑鼠右鍵→【新增檢視】→【Razor檢視】→範本【Empty(沒有模型)】→【新增】

@model IEnumerable<Employee>

@{
    ViewData["Title"] = "Index";
}

<table class="table table-striped table-bordered table-hover">
    <caption><h2>員工資料列表</h2></caption>
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(m => m.Name)
            </th>
            <th>
                @Html.DisplayNameFor(m => m.Mobile)
            </th>
            <th>
                @Html.DisplayNameFor(m => m.Email)
            </th>
            <th>
                @Html.DisplayNameFor(m => m.Department)
            </th>
            <th>
                @Html.DisplayNameFor(m => m.Title)
            </th>
            <th>異動</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var m in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(x => m.Name)
                </td>
                <td>
                    @Html.DisplayFor(x => m.Mobile)
                </td>
                <td>
                    @Html.DisplayFor(x => m.Email)
                </td>
                <td>
                    @Html.DisplayFor(x => m.Department)
                </td>
                <td>
                    @Html.DisplayFor(x => m.Title)
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@m.Id" class="btn btn-info">編輯</a>
                    <a asp-action="Details" asp-route-id="@m.Id" class="btn btn-primary">明細</a>
                    <a asp-action="Delete" asp-route-id="@m.Id" class="btn btn-danger">刪除</a>
                </td>
            </tr>
        }
    </tbody>
</table>

<p>
    <a asp-action="Create" class="btn btn-warning">新增員工資料</a>
</p>

顯示員工明細資料
1️⃣在Employees控制器建立Details方法,主要利用FirstOrDefaultAsync()方法查詢員工資料,其餘只是防呆的判斷程式。
路徑🔗Controllers/EmployeesController.cs

// GET: Employees/Details/5
public async Task<IActionResult> Details(int? id)
{
    //檢查是否有員工Id的判斷
    if (id == null || _context.Employees == null)
    {
        var msgObject = new
        {
            statuscode = StatusCodes.Status400BadRequest,
            error = "無效的請求,必須提供Id編號!",
            url = "The url example : /Employees/Details/5"
        };

        return new BadRequestObjectResult(msgObject);
    }

    //以Id找尋員工資料
    var employee = await _context.Employees.FirstOrDefaultAsync(m => m.Id == id);

    //如果沒有找到員工,回傳NotFound
    if (employee == null)
    {
        return NotFound();
    }

    return View(employee);
}

2️⃣建立檢視,如上一動作之方法

@model Employee

@{
    ViewData["Title"] = "Create";
}

<h4 class="alert alert-danger">員工個人資料明細</h4>
<div>
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(m => m.Name)
        </dt>
        <dd class="col-sm-9">
            @Html.DisplayFor(m => m.Name)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(m => m.Mobile)
        </dt>
        <dd class="col-sm-9">
            @Html.DisplayFor(m => m.Mobile)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(m => m.Email)
        </dt>
        <dd class="col-sm-9">
            @Html.DisplayFor(m => m.Email)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(m => m.Department)
        </dt>
        <dd class="col-sm-9">
            @Html.DisplayFor(m => m.Department)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(m => m.Title)
        </dt>
        <dd class="col-sm-9">
            @Html.DisplayFor(m => m.Title)
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.Id">編輯</a> |
    <a asp-action="Index">返回員工列表</a>
</div>

新增員工資料
1️⃣在Employees控制器建立Create方法

// GET: Employees/Create
[HttpGet]
public IActionResult Create()
{
    return View();
}

// POST: Employees/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,Mobile,Email,Department,Title")] Employee employee)
{
    //用ModelState.IsValid判斷資料是否通過驗證
    if (ModelState.IsValid)
    {
        //將entity加入DbSet
        _context.Employees.Add(employee);
        //_context.Add<Employee>(employee);
        //_context.Add(employee);
        //將資料異動儲存到資料庫
        await _context.SaveChangesAsync();
        //導向至Index動作方法
        return RedirectToAction(nameof(Index));
    }

    return View(employee);
}

2️⃣建立檢視,如上一動作之方法

3️⃣利用Data Annotations為Model加上驗證規則
路徑🔗Model/Employee.cs

namespace Mvc7_HtmlHelpers.Models
{
    public class Employee
    {
        public int Id { get; set; }
        [Required]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "最少需3個字元!")]
        public string Name { get; set; }
        [Required]
        [RegularExpression(@"^\09d{2}\-?\d{3}\-?\d{3}$", ErrorMessage = "需為09xx-xxx-xxx格式")]
        public string Mobile { get; set; }
        [Required(ErrorMessage = "請輸入Email")]
        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }
        [Required(ErrorMessage = "請輸入Department")]
        public string Department { get; set; }
        [Required(ErrorMessage = "請輸入Title")]
        public string Title { get; set; }
    }
}

編輯員工資料
1️⃣在Employees控制器建立Edit方法

// GET: Employees/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null || _context.Employees == null)
    {
        return NotFound();
    }

    var employee = await _context.Employees.FindAsync(id);

    if (employee == null)
    {
        return NotFound();
    }

    return View(employee);
}

// POST: Employees/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,Mobile,Email,Department,Title")] Employee employee)
{
    //檢查編輯id與Entity的Id是否相等
    if (id != employee.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            //更新employee實體
            _context.Employees.Update(employee);
            //_context.Update<Employee>(employee);
            //_context.Update(employee);
            await _context.SaveChangesAsync();  //將資料異動儲存到資料庫
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!EmployeeExists(employee.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }

    return View(employee);
}

2️⃣建立檢視,如上一動作之方法

刪除員工資料
1️⃣在Employees控制器建立Delete方法

        // GET: Employees/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            //檢查是否有提供id
            if (id == null || _context.Employees == null)
            {
                return NotFound();
            }

            //以Id找尋員工資料
            var employee = await _context.Employees
                .FirstOrDefaultAsync(m => m.Id == id);

            //如果沒有找到員工,回傳NotFound
            if (employee == null)
            {
                return NotFound();
            }

            return View(employee);
        }

        // POST: Employees/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            if (_context.Employees == null)
            {
                return Problem("Entity set 'CmsContext.Employees'  is null.");
            }

            //以Id找尋Entity,然後刪除
            var employee = await _context.Employees.FindAsync(id);

            if (employee != null)
            {
                //將該筆資料移除
                _context.Employees.Remove(employee);
                await _context.SaveChangesAsync();  //將資料異動儲存到資料庫
            }
            
            return RedirectToAction(nameof(Index));
        }

        private bool EmployeeExists(int id)
        {
          return _context.Employees.Any(e => e.Id == id);
        }
    }
}

2️⃣建立檢視,如上一動作之方法

以上就是如何用Html Helpers建立完整CRUD表單的方法啦~
那麼今天的文章就到這邊結束啦~明天見~See ya!(。•̀ᴗ-)


上一篇
Day23:Tag Helpers搭配Razor使用的常見語法
下一篇
Day25:View Component的使用方法
系列文
ASP.NET Core 30日成長路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言